Skip to content

docs: units of measure in every Python docstring (#90) - #169

Merged
ssmichael1 merged 2 commits into
mainfrom
docs/units-in-docstrings
Aug 31, 2026
Merged

docs: units of measure in every Python docstring (#90)#169
ssmichael1 merged 2 commits into
mainfrom
docs/units-in-docstrings

Conversation

@ssmichael1

Copy link
Copy Markdown
Owner

Closes #90

Systematic sweep so every Python-facing docstring states the unit of measure for each argument, return value, attribute and property that has a physical dimension. Convention is SI throughout: positions in meters, velocities in m/s, accelerations in m/s², angles in radians unless the name ends in _deg, durations in seconds (Julian dates in days), mass kg, area m², GM m³/s², density kg/m³, temperature K, F10.7 in sfu. TLE fields keep their native TLE units (degrees, revs/day, revs/day², revs/day³, 1/Earth-radii for B*).

Docstrings only — no code, signature or stub-type changes, no reformatting of unrelated prose. Where a docstring already stated the unit it was left alone.

The SGP4 callout (the reporter's example)

satkit.sgp4 (both satkit.pyi and the runtime __doc__ in pysgp4.rs) now says explicitly that position and velocity are returned in meters and meters/second in the TEME frame, with a note that the canonical Vallado implementation and most other SGP4 libraries return km and km/s and that satkit converts so SGP4 output matches every other position/velocity in the library. The output shapes are listed too — (3,), (Ntime, 3), (Ntle, 3), (Ntle, Ntime, 3) — taken from the reshape logic in pysgp4.rs.

Files touched (~112 docstring hunks, 18 files)

Stubs (python/satkit/): satkit.pyi (TLE fields, sgp4, time JD/MJD/unixtime/GPS-seconds, quaternion.from_axis_angle degrees→radians fix, itrfcoord.move_with_heading return, consts.wgs84_f, satstate/propresult covariance and STM block units, propsettings abs/rel error), frametransform.pyi (state-transform Returns; the *_approx and transform_state_approx functions had no Args/Returns at all), moon.pyi (moonphase ranges are degrees; illumination unitless 0–1), spaceweather.pyi (F10.7 keys in sfu).

Runtime docstrings (python/src/): pytle.rs, pysgp4.rs, pyinstant.rs, pyconsts.rs (also corrects jgm3_a which was labelled m³/s² — it is meters), pyquaternion.rs (rotx/roty/rotz summaries said "degrees"), pysatstate.rs, pypropresult.rs, pypropsettings.rs, pypropagate.rs, pythrust.rs, pyframetransform.rs, pylpephem_sun.rs (shadowfunc had no docstring), pyspaceweather.rs. Several getters/classes that had no runtime docstring at all (satstate, propsettings, propresult getters, time.from_gps_week_and_second) got one matching the stub.

Already complete and untouched: sun.pyi, planets.pyi, jplephem.pyi, density.pyi, utils.pyi, __init__.pyi, and their .rs counterparts; geodetic, itrfcoord (bar one return), thrust, ecomparams, satproperties, lambert, propagate stubs.

Excluded: kepler

python/src/pykepler.rs and the class kepler: section of satkit.pyi are deliberately untouched (verified byte-identical to main) — that class is being rewritten on a separate branch and edits here would only conflict.

Left alone (needs a decision, not a docstring)

  • satkit.density.nrlmsise(altitude, latitude, longitude, time) float form has a stub-vs-runtime unit mismatch. The stub names the parameters latitude_rad / longitude_rad and documents radians, but pydensity.rs passes the floats straight to nrlmsise::nrlmsise, which takes degrees (the itrfcoord overload calls latitude_deg() for the same slots). Fixing it means changing either the stub signature or the binding, both outside a docstring-only PR. Suggest a follow-up issue.
  • propsettings.abs_error is described as "in the units of the state (meters for position, m/s for velocity)" based on settings.rs ("infinity norm of the state") and the tolerance being passed through unscaled; worth a second look if the integrator scales internally.
  • spaceweather.get() cp / kp — indices, no unit word added.

Non-unit stub/runtime drifts noticed but out of scope: pylpephem_moon.rs::phase_name Returns says str|list (it returns moonphase); pylpephem_planets.rs::heliocentric_pos Args are in the wrong order/type vs the signature; pypropagate.rs still names the positional arg state0 where the stub says state.

Verification

  • cargo fmt --all -- --check, cargo clippy --workspace --all-targets -- -D warnings: clean
  • pip install -e . --no-build-isolation (in a private venv, not the shared site-packages), then stubtest exactly as CI runs it (--allowlist python/stubtest_allowlist.txt --ignore-positional-only --ignore-disjoint-bases): no issues in 10 modules
  • pytest python/test -q with SATKIT_DATA / SATKIT_TESTVEC_ROOT: 191 passed, 2 skipped
  • compiled satkit.sgp4.__doc__ checked for the meters / kilometers wording

🤖 Generated with Claude Code

https://claude.ai/code/session_01PG969yapJ84DJceKt21Wen

ssmichael1 and others added 2 commits August 30, 2026 20:29
Systematic sweep of the .pyi stubs and the #[pyfunction]/#[pymethods]
docstrings so every dimensioned argument, return value, attribute and
property states its unit (SI: meters, m/s, m/s^2, radians unless the
name ends in _deg; TLE fields in their native TLE units). sgp4 now says
explicitly that its TEME output is meters and m/s, not the km / km/s of
the canonical Vallado implementation, and lists the output shapes.

Docstrings only: no code, signature or stub-type changes. The kepler
class (python/src/pykepler.rs and the class kepler section of
satkit.pyi) is left untouched; it is being rewritten on another branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PG969yapJ84DJceKt21Wen
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PG969yapJ84DJceKt21Wen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docs Request: Be precise with unit-of-measure

1 participant